home *** CD-ROM | disk | FTP | other *** search
/ Programmers Heaven 2 / Programmers Heaven 2.iso / files / graphics / library / wgt51_r2.zip / WGT5 / 3D / WREND.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-03  |  39.5 KB  |  1,468 lines

  1. #include <conio.h>
  2. #include <math.h>
  3. #include <stdlib.h>
  4. #include <time.h>
  5. #include <dos.h>
  6. #include <wgt5.h>
  7. #include <wgtvesa.h>
  8.  
  9. /* WGT 3D Rendering Library
  10.    Copyright 1995 Egerter Software */
  11.  
  12. /* Triangle Rendering Methods */
  13. #define WIREFRAME              0
  14. #define SOLID                  1
  15. #define GOURAUD                2
  16. #define TEXTURE                3
  17. #define FLAT_SHADED_TEXTURE    4
  18. #define GOURAUD_SHADED_TEXTURE 5
  19. #define TRANSLUCENT_TEXTURE    6
  20. #define TRANSLUCENT_GOURAUD    7
  21.  
  22. #define M_PI 3.1415926535897932384626
  23.  
  24. #define POLYBUF  10000           /* Maximum polys per frame */
  25. #define OBJBUF     100          /* Maximum objects in world */
  26. #define MAXKEYS 100             /* Maximum animation keys per object */
  27. #define MAXCHILDREN 10          /* Maximum child objects per parent */
  28. #define MAX_TEXTURES 10         /* Maximum textures loaded at once */
  29.  
  30. float render_shades = 64;       /* Number of colors reserved for shading a
  31.                    single color */
  32. int render_all = 0;             /* 0 = backface removal */
  33.  
  34.  
  35. /* Our 3D system structures */
  36. typedef struct
  37. {
  38.   float         x, y, z;
  39. } point3d;                      /* A single 3D point */
  40.  
  41.  
  42. typedef struct
  43. {
  44.   point3d       local;
  45.   point3d       world;
  46.   point3d       normal;
  47.   int           screenx, screeny;
  48.   unsigned char connected;
  49.   unsigned char rotated;
  50. } vertex;                       /* A vertex of a polygon */
  51.  
  52.  
  53. typedef struct
  54. {
  55.   int           vertex1;
  56.   int           vertex2;
  57.   int           vertex3;
  58.   int           type;
  59.   point3d       normal;
  60.   point3d       center;
  61.   short         status;
  62.   unsigned char color;
  63. } triangle_3d;                   /* A 3D triangle */
  64.  
  65.  
  66. typedef struct
  67. {
  68.  float          sx, sy, sz; /* Scale */
  69.  float          tx, ty, tz; /* Translation */
  70.  float          rx, ry, rz; /* Rotation */
  71.  int            framenumber;
  72.  char           update_scale;
  73.  char           update_rotation;
  74.  char           update_translation;
  75. } keydata;                      /* Key animation data */
  76.  
  77.  
  78. typedef struct
  79. {
  80.   int           start_poly;
  81.   int           end_poly;
  82.   int           startpoints;
  83.   int           points;
  84.  
  85.   float         minx;
  86.   float         maxx;
  87.   float         miny;
  88.   float         maxy;
  89.   float         minz;
  90.   float         maxz;
  91.  
  92.   /* Added for animation */
  93.   float         translatex;
  94.   float         translatey;  /* Added to each vertex each frame */
  95.   float         translatez;
  96.  
  97.   float         pivotx;
  98.   float         pivoty;  /* Pivot location for this object */
  99.   float         pivotz;
  100.  
  101.   float         scalex;
  102.   float         scaley;  /* Multiplied by each vertex based on the distance */
  103.   float         scalez;  /* from the pivot location */
  104.  
  105.   float         rotatex;
  106.   float         rotatey;  /* Each vertex is rotated by this amount */
  107.   float         rotatez;
  108.  
  109.   /* Hierarchy */
  110.   short int     level;
  111.   short         maxchild;               /* Number of children */
  112.   unsigned short int children[MAXCHILDREN];
  113.   short         parent;                 /* Parent of this object */
  114.  
  115.   keydata       keylist[MAXKEYS];       /* Array of key frames */
  116.   int           maxframe;               /* Max animation frame */
  117.   int           currentframe;           /* Current animation frame */
  118.   
  119.   int           tstepsleft;             /* Translation steps left */
  120.   int           rstepsleft;             /* Rotation steps left */
  121.  
  122.   char          name[15];               /* Name of object */
  123. } object_3d;
  124.  
  125.  
  126. struct {
  127.   float lens;
  128.   float fov;
  129. } cameras[9] = { 15, 115, 20, 94.28571, 24, 84, 28, 76.36, 35, 63,
  130.          50, 46, 85, 28, 135, 18, 200, 12 };
  131.  
  132. /* For shaded texture mapping */
  133. unsigned char *render_shadetable;
  134.  
  135. tpoint          renderpoly[3];  /* Used to draw one triangle at a time */
  136.  
  137. typedef struct {
  138.   int           number;                 /* Sorted polygon # */
  139.   float         depth;                  /* Center depth of polygon */
  140. } sort;
  141.  
  142. sort sorted_polys[POLYBUF];
  143.  
  144.  
  145. typedef struct
  146. {
  147.  long           sx[3];
  148.  long           sy[3];
  149. } polytexture;
  150.  
  151. polytexture     ptext[POLYBUF];         /* Holds texture coordinates for each
  152.                        triangle in the polylist */
  153.  
  154. point3d         camera;                 /* Camera position */
  155. point3d         camera_norm;            /* Camera position */
  156. point3d         focus;                  /* Target position */
  157. point3d         tvect;                  /* Eye vector */
  158.  
  159. struct {
  160.   point3d       world;
  161.   point3d       normal;
  162. } light;                                /* Light position */
  163.  
  164. float           fov;                    /* Field of view in degrees */
  165. float           dist;                   /* Distance from viewer */
  166. float           m11, m12, m21, m22, m23, m31, m32, m33;
  167.  
  168. triangle_3d     polylist[POLYBUF];      /* Polygon list for world */
  169. object_3d       objectlist[OBJBUF];     /* Object list for world */
  170.  
  171. block           textures[MAX_TEXTURES];
  172.  
  173. float           camera_x, camera_y, camera_z;
  174. float           focus_x, focus_y, focus_z;
  175. float           light_x, light_y, light_z;
  176. float           camera_angle;
  177. int             worldpoints;
  178. int             totalpoly = 0;
  179. int             totalobjects = 0;
  180.  
  181.  
  182. /* The following are defined in wrendani.c, used for moving, scaling, and 
  183.    rotating objects. */
  184.  
  185. extern void translate_object (object_3d *obj, vertex *pts, float x, float y, 
  186.                   float z);
  187. /* Adds x,y,z to each 3D point in the object */
  188.  
  189.  
  190. extern void scale_object     (object_3d *obj, vertex *pts, 
  191.                   float x, float y, float z,
  192.                   float px, float py, float pz);
  193. /* Scales by x,y,z, based on the distance from px,py,pz */
  194.  
  195.  
  196. extern void rotate_object    (object_3d *obj, vertex *pts, 
  197.                   float x, float y, float z,
  198.                   float px, float py, float pz);
  199. /* Rotates the object by x,y,z around the center point px,py,pz */
  200.  
  201.  
  202. extern void set_object_pivot (object_3d *obj, float x, float y, float z);
  203. /* Sets x,y,z as the center of the object */
  204.  
  205.  
  206. extern void rotate_point (float *ptx, float *pty, float *ptz,
  207.               float x, float y, float z,
  208.               float px, float py, float pz);
  209. /* Rotates a single point by x,y,z around px,py,pz */
  210.  
  211.  
  212. /* The following are defined in this file: */
  213.  
  214. void map_plane (float x, float y, float z, long *u, long *v, float scale);
  215. /* Given a 3D point, maps the point onto the x/y plane */
  216.  
  217. float dot_product (point3d *a, point3d *b);
  218. /* Compute the dot product between two 3D vectors */
  219.  
  220. void wset_focus (float a, float b, float c);
  221. /* Sets where the camera is looking at */
  222.  
  223. void wset_camera (float a, float b, float c);
  224. /* Sets the position of the camera */
  225.  
  226. void wset_light (float a, float b, float c);
  227. /* Sets the position of the light */
  228.  
  229. void wset_view (void);
  230. /* Sets up the viewing matrix based on the camera position and direction */
  231.  
  232. void wworld_2_view (object_3d *obj, int *drawtotal, vertex *vlist);
  233. /* Transform the 3D coordinates to 2D coordinates */
  234.  
  235. void calc_normal (vertex *wp1, vertex *wp2, vertex *wp3, point3d *norm);
  236. /* Calculates a normal vector given three vertices */
  237.  
  238. void map_points (short obj, vertex *pts, float scale);
  239. /* Map all the texture coordinates onto a plane, given an object and a scale */
  240.  
  241. int sortkeys (keydata *a, keydata *b);
  242. /* Sorts the animation keys by their frame number */
  243.  
  244. void adjust_object (object_3d *objp, float rx, float ry, float rz, 
  245.             float px, float py, float pz);
  246. /* Modify an object's animation data if it has a parent */
  247.  
  248. void duplicate_frame (object_3d *obj, int frame, int framenumber);
  249. /* Copies one animation key to another */
  250.  
  251. void build_hierarchy (void);
  252. /* Connects children and parents together */
  253.  
  254. void add_key_translate (object_3d *obj, int framenumber, float x, float y, 
  255.             float z);
  256. /* Adds a translation animation key */
  257.  
  258. void add_key_scale (object_3d *obj, int framenumber, float x, float y,
  259.             float z);
  260. /* Adds a scale animation key */
  261.  
  262. void add_key_rotate (object_3d *obj, int framenumber, float x, float y, 
  263.             float z);
  264. /* Adds a rotation animation key */
  265.  
  266. int find_object (char *name);
  267. /* Given the name of an object, returns the index in objectlist */
  268.  
  269. void add_child (int parent, int child);
  270. /* Adds a child to a parent object */
  271.  
  272. void load_3ds (char *filename, vertex *pts);
  273. /* Loads a 3D Studio file */
  274.  
  275. int compare (sort *a, sort *b);
  276. /* Used for sorting */
  277.  
  278. void draw_polys (vertex *pts, int drawtotal);
  279. /* Draws the polygons */
  280.  
  281. void wset_object_color (int obj, unsigned char col);
  282. /* Sets the color of each triangle in an object, used for solid, gouraud, and
  283.    texture.  For textured objects, the color represents the texture number
  284.    from the textures array. */
  285.  
  286. void wset_object_type (int obj, int type);
  287. /* Sets the rendering method for an object */
  288.  
  289. void wreset_3d_system (void);
  290. /* Resets the engine so you can load in a new object */
  291.  
  292. /***************************************************************************/
  293. float dot_product (point3d *a, point3d *b)
  294. /* Compute the dot product between two 3D vectors */
  295. {
  296.   return ( (a->x * b->x) + (a->y * b->y) + (a->z * b->z) );
  297. }
  298.  
  299.  
  300. void wset_focus (float a, float b, float c)
  301. /* Sets where the camera is looking at */
  302. {
  303.   focus.x = a;
  304.   focus.y = b;
  305.   focus.z = c;
  306. }
  307.  
  308.  
  309. void wset_camera (float a, float b, float c)
  310. /* Sets the position of the camera */
  311. {
  312. float norm;
  313.  
  314.   camera.x = a;
  315.   camera.y = b;
  316.   camera.z = c;
  317.   norm = sqrt( (a * a) + (b * b) + (c * c) );
  318.   camera_norm.x = a / norm;
  319.   camera_norm.y = b / norm;
  320.   camera_norm.z = c / norm;
  321. }
  322.  
  323.  
  324. void wset_light (float a, float b, float c)
  325. /* Sets the position of the light */
  326. {
  327. float norm;
  328.  
  329.   light.world.x = a;
  330.   light.world.y = b;
  331.   light.world.z = c;
  332.   norm = sqrt( (a * a) + (b * b) + (c * c) );
  333.   light.normal.x = a / norm;
  334.   light.normal.y = b / norm;
  335.   light.normal.z = c / norm;
  336. }
  337.  
  338.  
  339. void wset_view (void)
  340. /* Sets up the viewing matrix based on the camera position and direction */
  341. {
  342. float lambda;
  343. float tlength;
  344.  
  345.   lambda = ((fov / 180.0) * 3.1415);
  346.   dist = 100.0 / sin(lambda / 2);
  347.  
  348.   tvect.x = focus.x - camera.x;
  349.   tvect.y = focus.y - camera.y;
  350.   tvect.z = focus.z - camera.z;
  351.   lambda = sqrt ( (tvect.x * tvect.x) + (tvect.y * tvect.y) );
  352.   tlength = sqrt ( (tvect.x * tvect.x) + (tvect.y * tvect.y) + (tvect.z * tvect.z) );
  353.  
  354.   m11 = tvect.y / lambda;
  355.   m12 = -tvect.x / lambda;
  356.   m21 = (tvect.x * tvect.z) / (lambda * tlength);
  357.   m22 = (tvect.y * tvect.z) / (lambda * tlength);
  358.   m23 = -lambda / tlength;
  359.   m31 = tvect.x / tlength;
  360.   m32 = tvect.y / tlength;
  361.   m33 = tvect.z / tlength;
  362. }
  363.  
  364.  
  365. void wworld_2_view (object_3d *obj, int *drawtotal, vertex *vlist)
  366. /* Transform the 3D coordinates to 2D coordinates */
  367. {
  368. int poly, start, finish;
  369. float xo, yo, zo;
  370. float xo2, yo2, zo2;
  371. float xo3, yo3, zo3;
  372. float min_depth, max_depth, temp;
  373. triangle_3d *ptr;
  374. point3d lineofsite;
  375. vertex *vptr;
  376. vertex *vptr2;
  377. vertex *vptr3;
  378. float xres, yres;
  379.  
  380.   xres = (float)WGT_SYS.xres / 2.0;
  381.   yres = (float)WGT_SYS.yres / 2.0;
  382.   start = obj->start_poly;
  383.   finish = obj->end_poly;
  384.  
  385.   for (poly = start; poly <= finish; poly++)
  386.   {
  387.     ptr = &polylist[poly];
  388.     vptr = &vlist[ptr->vertex1];
  389.     vptr2 = &vlist[ptr->vertex2];
  390.     vptr3 = &vlist[ptr->vertex3];
  391.  
  392.     lineofsite.x = vptr->local.x - camera.x;
  393.     lineofsite.y = vptr->local.y - camera.y;
  394.     lineofsite.z = vptr->local.z - camera.z;
  395.     if ((dot_product (&lineofsite, &ptr->normal) >= 0) || (render_all))
  396.     {
  397.       if (vptr->rotated == 0)
  398.       {
  399.        xo = vptr->local.x - camera.x;
  400.        yo = vptr->local.y - camera.y;
  401.        zo = vptr->local.z - camera.z;
  402.  
  403.        vptr->world.z = (xo * m31) + (yo * m32) + (zo * m33);
  404.       }
  405.       if (vptr2->rotated == 0)
  406.       {
  407.        xo2 = vptr2->local.x - camera.x;
  408.        yo2 = vptr2->local.y - camera.y;
  409.        zo2 = vptr2->local.z - camera.z;
  410.  
  411.        vptr2->world.z = (xo2 * m31) + (yo2 * m32) + (zo2 * m33);
  412.       }
  413.       if (vptr3->rotated == 0)
  414.       {
  415.        xo3 = vptr3->local.x - camera.x;
  416.        yo3 = vptr3->local.y - camera.y;
  417.        zo3 = vptr3->local.z - camera.z;
  418.  
  419.        vptr3->world.z = (xo3 * m31) + (yo3 * m32) + (zo3 * m33);
  420.       }
  421.       if ( (vptr->world.z > 0) || (vptr2->world.z > 0) || (vptr3->world.z > 0))
  422.       {
  423.     if (vptr->rotated == 0) 
  424.     {
  425.       vptr->world.x = (xo * m11) + (yo * m12);
  426.       vptr->world.y = (xo * m21) + (yo * m22) + (zo * m23);
  427.       /* PROJECTION */
  428.       temp = dist / vptr->world.z;
  429.       vptr->screenx = (vptr->world.x * temp) + xres;
  430.       vptr->screeny = (vptr->world.y * temp) + yres;
  431.       vptr->rotated = 1;
  432.     }
  433.     if (vptr2->rotated == 0)
  434.     {
  435.       vptr2->world.x = (xo2 * m11) + (yo2 * m12);
  436.       vptr2->world.y = (xo2 * m21) + (yo2 * m22) + (zo2 * m23);
  437.       /* PROJECTION */
  438.       temp = dist / vptr2->world.z;
  439.       vptr2->screenx = (vptr2->world.x * temp) + xres;
  440.       vptr2->screeny = (vptr2->world.y * temp) + yres;
  441.       vptr2->rotated = 1;
  442.     }
  443.     if (vptr3->rotated == 0)
  444.     {
  445.       vptr3->world.x = (xo3 * m11) + (yo3 * m12);
  446.       vptr3->world.y = (xo3 * m21) + (yo3 * m22) + (zo3 * m23);
  447.       /* PROJECTION */
  448.       temp = dist / vptr3->world.z;
  449.       vptr3->screenx = (vptr3->world.x * temp) + xres;
  450.       vptr3->screeny = (vptr3->world.y * temp) + yres;
  451.       vptr3->rotated = 1;
  452.     }
  453.     if ( ((vptr->screenx >= 0) || (vptr2->screenx >= 0) || (vptr3->screenx >= 0))
  454.       && ((vptr->world.z > 1) && (vptr2->world.z > 1) && (vptr3->world.z > 1))
  455.       && ((vptr->screeny >= 0) || (vptr2->screeny >= 0) || (vptr3->screeny >= 0))
  456.       && ((vptr->screenx < WGT_SYS.xres) || (vptr2->screenx < WGT_SYS.xres) || (vptr3->screenx < WGT_SYS.xres))
  457.       && ((vptr->screeny < WGT_SYS.yres) || (vptr2->screeny < WGT_SYS.yres) || (vptr3->screeny < WGT_SYS.yres)) )
  458.     {
  459.       sorted_polys[*drawtotal].number = poly;
  460.       /* Rotate center of polygon */
  461.  
  462.       /* Center of polygon, Z sorting */
  463.       /* xo = ptr->center.x - camera.x;
  464.       yo = ptr->center.y - camera.y;
  465.       zo = ptr->center.z - camera.z;
  466.       sorted_polys[*drawtotal].depth = (xo * m31) + (yo * m32) + (zo * m33); */
  467.       
  468.       /* Farthest Z Sorting */
  469.       /* zo = vptr->world.z;
  470.       if (vptr2->world.z > zo)
  471.         zo = vptr2->world.z;
  472.       if (vptr3->world.z > zo)
  473.         zo = vptr3->world.z;
  474.       sorted_polys[*drawtotal].depth = zo;*/
  475.  
  476.       /* Average Z Sorting */
  477.       sorted_polys[*drawtotal].depth = (vptr->world.z + vptr2->world.z +
  478.         vptr3->world.z) / 3.0;
  479.  
  480.       *drawtotal = *drawtotal + 1;
  481.     }
  482.       }
  483.     }
  484.   }
  485. }
  486.  
  487.  
  488. void calc_normal (vertex *wp1, vertex *wp2, vertex *wp3, point3d *norm)
  489. /* Calculates a normal vector given three vertices */
  490. {
  491. point3d a, b;
  492.  
  493.   a.x = wp2->local.x - wp1->local.x;
  494.   a.y = wp2->local.y - wp1->local.y;
  495.   a.z = wp2->local.z - wp1->local.z;
  496.  
  497.   b.x = wp3->local.x - wp1->local.x;
  498.   b.y = wp3->local.y - wp1->local.y;
  499.   b.z = wp3->local.z - wp1->local.z;
  500.  
  501.   norm->x = (a.y * b.z) - (a.z * b.y);
  502.   norm->y = (a.z * b.x) - (a.x * b.z);
  503.   norm->z = (a.x * b.y) - (a.y * b.x);
  504.   
  505.   /* Normalize it */
  506.   a.x = sqrt((norm->x * norm->x) + (norm->y * norm->y) + (norm->z * norm->z));
  507.   norm->x /= a.x;
  508.   norm->y /= a.x;
  509.   norm->z /= a.x;
  510. }
  511.  
  512.  
  513.  
  514.  
  515.  
  516. void map_points (int obj, vertex *pts, float scale)
  517. /* Map all the texture coordinates onto a plane, given an object and a scale */
  518. {
  519. int ply;
  520. int vert;
  521. triangle_3d *polyptr;
  522.  
  523.  
  524.   for (ply = objectlist[obj].start_poly; ply <= objectlist[obj].end_poly; ply++)
  525.    { 
  526.     polyptr = &polylist[ply];
  527.     map_plane (pts[polyptr->vertex1].local.x, pts[polyptr->vertex1].local.y, 
  528.            pts[polyptr->vertex1].local.z, &ptext[ply].sx[0], 
  529.            &ptext[ply].sy[0], scale);
  530.     map_plane (pts[polyptr->vertex2].local.x, pts[polyptr->vertex2].local.y, 
  531.            pts[polyptr->vertex2].local.z, &ptext[ply].sx[1], 
  532.            &ptext[ply].sy[1], scale);
  533.     map_plane (pts[polyptr->vertex3].local.x, pts[polyptr->vertex3].local.y, 
  534.            pts[polyptr->vertex3].local.z, &ptext[ply].sx[2], 
  535.            &ptext[ply].sy[2], scale);
  536.    }
  537. }
  538.  
  539.  
  540.  
  541. int sortkeys (keydata *a, keydata *b)
  542. /* Sorts the animation keys by their frame number */
  543. {
  544.  if (a->framenumber < b->framenumber)
  545.    return -1;
  546.  else if (a->framenumber > b->framenumber)
  547.    return 1;
  548.  else return 0;
  549. }
  550.  
  551.  
  552.  
  553.  
  554. void adjust_object (object_3d *objp, float rx, float ry, float rz, 
  555.             float px, float py, float pz)   
  556. /* Modify an object's animation data if it has a parent */
  557. {
  558. int child; 
  559. int frame;
  560. object_3d *objc; 
  561. keydata *key;
  562.      
  563.  
  564.  if (objp->maxchild > -1)
  565.   {
  566.    for (child = 0; child <= objp->maxchild; child++)
  567.     {
  568.      objc = &objectlist[objp->children[child]];
  569.      rotate_point (&objc->pivotx, &objc->pivoty, &objc->pivotz, 
  570.             -rx, -ry, -rz, 0, 0, 0);
  571.      rotate_point (&objc->pivotx, &objc->pivoty, &objc->pivotz, 
  572.            objc->keylist[0].rx, objc->keylist[0].ry, objc->keylist[0].rz, 
  573.            0, 0, 0);
  574.      objc->pivotx += px;
  575.      objc->pivoty += py;
  576.      objc->pivotz += pz;
  577.       
  578.      if (objc->maxframe > -1)
  579.      for (frame = 1; frame <= objc->maxframe; frame++)
  580.       {
  581.        key = &objc->keylist[frame];
  582.        rotate_point (&key->rx, &key->ry, &key->rz, -rx, -ry, -rz, 0, 0, 0);
  583. //       rotate_point (&key->rx, &key->rx, &key->rx, 
  584.            //objc->keylist[0].rx, objc->keylist[0].ry, objc->keylist[0].rz, 
  585.            //0, 0, 0);
  586.      
  587.        rotate_point (&key->tx, &key->ty, &key->tz, rx, ry, rz, 0, 0, 0);
  588.       }
  589.  
  590.       
  591.     
  592.      adjust_object (objc, rx, ry, rz, px, py, pz);
  593.     }
  594.  }
  595. }
  596.  
  597.  
  598. void duplicate_frame (object_3d *obj, int frame, int framenumber)
  599. /* Copies one animation key to another */
  600. {
  601. int lastkey; 
  602.  
  603.  lastkey = obj->maxframe+1;
  604.  memcpy (&obj->keylist[lastkey], &obj->keylist[frame], sizeof (keydata));
  605.  obj->keylist[lastkey].framenumber = framenumber;
  606.  obj->maxframe++;
  607.  obj->keylist[lastkey].rx = 0;
  608.  obj->keylist[lastkey].ry = 0;
  609.  obj->keylist[lastkey].rz = 0;
  610.  obj->keylist[lastkey].update_rotation = 1;
  611.  obj->keylist[lastkey].update_translation = 0;
  612. }
  613.  
  614.  
  615.  
  616. #include <stddef.h>
  617.  
  618. void qsort (void  *base,
  619.         size_t nel,
  620.         size_t width,
  621.         int (*comp)(const void *, const void *))
  622. {
  623.       size_t wnel, gap, wgap, i, j, k;
  624.       char *a, *b, tmp;
  625.  
  626.       wnel = width * nel;
  627.       for (gap = 0; ++gap < nel;)
  628.         gap *= 3;
  629.       while ( gap /= 3 )
  630.       {
  631.         wgap = width * gap;
  632.         for (i = wgap; i < wnel; i += width)
  633.         {
  634.           for (j = i - wgap; ;j -= wgap)
  635.           {
  636.             a = j + (char *)base;
  637.             b = a + wgap;
  638.             if ( (*comp)(a, b) <= 0 )
  639.                   break;
  640.             k = width;
  641.             do
  642.             {
  643.                   tmp = *a;
  644.                   *a++ = *b;
  645.                   *b++ = tmp;
  646.             } while ( --k );
  647.             if (j < wgap)
  648.                   break;
  649.           }
  650.         }
  651.       }
  652. }
  653.  
  654.  
  655. void build_hierarchy (void)
  656. /* Connects children and parents together */
  657. {
  658. object_3d *objp;
  659. object_3d *objc;
  660.  
  661. int obj, obj2;
  662. int level;
  663. float rx, ry, rz;
  664. float crx, cry, crz;
  665.  
  666. int lastframe, testframe;
  667.  
  668.  
  669.  lastframe = 0;
  670.  /* Sort keyframes */
  671.  for (obj = 0; obj < totalobjects; obj++)
  672.   {
  673.    objp = &objectlist[obj];
  674.    qsort (objp->keylist, objp->maxframe+1, sizeof (keydata), sortkeys);          
  675.    
  676.    testframe = objp->keylist[objp->maxframe].framenumber;
  677.    if (testframe > lastframe)
  678.      lastframe = testframe;
  679.   }
  680.  
  681.  for (obj = 0; obj < totalobjects; obj++)
  682.   {
  683.    objp = &objectlist[obj];
  684.    objp->pivotx = objp->keylist[0].tx; 
  685.    objp->pivoty = objp->keylist[0].ty; 
  686.    objp->pivotz = objp->keylist[0].tz; 
  687.    
  688.    testframe = objp->keylist[objp->maxframe].framenumber;
  689.    if ((testframe != lastframe) && (objp->maxframe > 0))
  690.      duplicate_frame (objp, objp->maxframe, lastframe);
  691.   }
  692.  
  693.  
  694.  for (obj = 0; obj < totalobjects; obj++)
  695.   {
  696.    objp = &objectlist[obj];
  697.    
  698.    rx = objp->keylist[0].rx;
  699.    ry = objp->keylist[0].ry;
  700.    rz = objp->keylist[0].rz;
  701.    
  702.    crx = objp->pivotx;
  703.    cry = objp->pivoty;
  704.    crz = objp->pivotz;
  705.       
  706.    adjust_object (objp, rx, ry, rz, crx, cry, crz);
  707.   }
  708. }
  709.              
  710.              
  711. void add_key_translate (object_3d *obj, int framenumber, float x, float y, float z)
  712. /* Adds a translation animation key */
  713. {
  714. int key;
  715. int foundkey;
  716.  
  717.  foundkey = -1;
  718.  for (key = 0; key <= obj->maxframe; key++)
  719.   if (obj->keylist[key].framenumber == framenumber)
  720.     foundkey = key;
  721.  
  722.  if (foundkey == -1)
  723.   { 
  724.    obj->maxframe++;
  725.    foundkey = obj->maxframe;
  726.    obj->keylist[foundkey].framenumber = framenumber;
  727.   }
  728.  
  729.  obj->keylist[foundkey].tx = x;
  730.  obj->keylist[foundkey].ty = y;
  731.  obj->keylist[foundkey].tz = z;
  732.  obj->keylist[foundkey].update_translation = 1;
  733.  
  734. }
  735.  
  736.  
  737. void add_key_scale (object_3d *obj, int framenumber, float x, float y, float z)
  738. /* Adds a scale animation key */
  739. {
  740. int key;
  741. int foundkey;
  742.  
  743.  foundkey = -1;
  744.  for (key = 0; key <= obj->maxframe; key++)
  745.   if (obj->keylist[key].framenumber == framenumber)
  746.     foundkey = key;
  747.  
  748.  if (foundkey == -1)
  749.   { 
  750.    obj->maxframe++;
  751.    foundkey = obj->maxframe;
  752.    obj->keylist[foundkey].framenumber = framenumber;
  753.   }
  754.  
  755.  obj->keylist[foundkey].sx = x;
  756.  obj->keylist[foundkey].sy = y;
  757.  obj->keylist[foundkey].sz = z;
  758.  obj->keylist[foundkey].update_scale = 1;
  759. }
  760.  
  761.  
  762. void add_key_rotate (object_3d *obj, int framenumber, float x, float y, float z)
  763. /* Adds a rotation animation key */
  764. {
  765. int key;
  766. int foundkey;
  767.  
  768.  foundkey = -1;
  769.  for (key = 0; key <= obj->maxframe; key++)
  770.   if (obj->keylist[key].framenumber == framenumber)
  771.     foundkey = key;
  772.  
  773.  if (foundkey == -1)
  774.   { 
  775.    obj->maxframe++;
  776.    foundkey = obj->maxframe;
  777.    obj->keylist[foundkey].framenumber = framenumber;
  778.   }
  779.  
  780.  obj->keylist[foundkey].rx = x;
  781.  obj->keylist[foundkey].ry = y;
  782.  obj->keylist[foundkey].rz = z;
  783.  obj->keylist[foundkey].update_rotation = 1;
  784. }
  785.  
  786.  
  787. int find_object (char *name)
  788. /* Given the name of an object, returns the index in objectlist */
  789. {
  790. int obj;
  791. int found;
  792.  
  793.  found = -1;
  794.  for (obj = 0; obj < totalobjects; obj++)
  795.   {
  796.    if (strcmp (objectlist[obj].name, name) == 0)
  797.      found = obj;
  798.   }
  799.  
  800.  return (found);
  801. }
  802.  
  803.  
  804.  
  805. void add_child (int parent, int child)
  806. /* Adds a child to a parent object */
  807. {
  808.  objectlist[child].parent = parent;
  809.  objectlist[parent].maxchild++;
  810.  objectlist[parent].children[objectlist[parent].maxchild] = child;
  811. }
  812.  
  813.  
  814.  
  815. void load_3ds (char *filename, vertex *pts)
  816. /* Loads a 3D Studio file */
  817. {
  818. FILE *in;
  819. float camx, camy, camz;
  820. float tarx, tary, tarz;
  821. float lightx, lighty, lightz;
  822. float mat11, mat12, mat13, mat21, mat22, mat23, mat31, mat32, mat33,
  823.       mat41, mat42, mat43;
  824. float lens;
  825. float bank;
  826. float min_depth, max_depth;
  827. float x, y, z;
  828. unsigned short int p1, p2, p3, p4;
  829. char c;
  830. char objname[20];
  831. unsigned int nextobj;
  832. unsigned short vertices;
  833. unsigned short polys;
  834. int vertcnt;
  835. vertex *vptr, *vptr2, *vptr3;
  836. char buffer[120];
  837. int i, ctr;
  838. int hiernum;
  839. int prevobj;
  840.  
  841. long filelen;  
  842.  
  843. int numkeys;
  844. short framenumber;
  845. float rx, ry, rz;
  846. float rangle;
  847.  
  848. short level;
  849.  
  850. struct {
  851.   unsigned short chunk_id;
  852.   unsigned int   next_chunk;
  853. } chunk;
  854.  
  855.     
  856.   hiernum = -1;
  857.  
  858.   
  859.   vertcnt = 0;
  860.   totalobjects = 0;
  861.   totalpoly = 0;
  862.   
  863.   /* Library code */
  864.   if  (wgtlibrary == NULL)
  865.   {
  866.     if  ((libf = fopen (filename, "rb")) == NULL)
  867.       goto l3dsstop;
  868.   }
  869.   else
  870.   {
  871.     if  ((libf = fopen (wgtlibrary, "rb")) == NULL)
  872.       goto l3dsstop;
  873.     readheader ();
  874.     findfile (filename);
  875.     if  (lresult == 1)
  876.       fseek (libf, lfpos, SEEK_SET);
  877.     if  (checkpassword (password) == 0)
  878.     {
  879.       wsetmode (3);
  880.       printf ("Incorrect password");
  881.       exit (1);
  882.     }
  883.   }
  884.  
  885.   if  ((wgtlibrary != NULL) & (lresult == 0)) goto l3dsstop;
  886.   /* Library code */
  887.   in = libf;
  888.   
  889.   filelen = filelength (fileno(in));
  890.   fread (&chunk, 6, 1, in);
  891.   if (chunk.chunk_id == 0x4d4d)
  892.     while (!feof (in) && (ftell(in) < filelen))
  893.     {
  894.       fread (&chunk, 6, 1, in);
  895.       switch (chunk.chunk_id) {
  896.     case 0x3d3d : // Loading mesh
  897.               break;
  898.     case 0x4000 : // Found object
  899.               nextobj = ftell (in) + chunk.next_chunk - 6;
  900.               objectlist[totalobjects].points = 0;
  901.               objectlist[totalobjects].maxchild = -1;
  902.               c = 0;
  903.               
  904.               /* Read the object name */
  905.               do {
  906.             objname[c] = fgetc (in);
  907.             c++;
  908.               } while (objname[c-1] != 0);
  909.               strcpy (objectlist[totalobjects].name, objname);
  910.               break;
  911.     case 0x4100 : // Triangular polygon object
  912.               break;
  913.     case 0x4110 : // Loading vertices
  914.               fread (&vertices, 2, 1, in);
  915.               objectlist[totalobjects].points = vertices;
  916.               objectlist[totalobjects].startpoints = vertcnt;
  917.               for (i = 0; i < vertices; i++)
  918.               {
  919.             fread (&x, 4, 1, in);
  920.             fread (&y, 4, 1, in);
  921.             fread (&z, 4, 1, in);
  922.             pts[vertcnt].local.x = x;
  923.             pts[vertcnt].local.y = y;
  924.             pts[vertcnt].local.z = z;
  925.             pts[vertcnt].normal.x = 0;
  926.             pts[vertcnt].normal.y = 0;
  927.             pts[vertcnt].normal.z = 0;
  928.             pts[vertcnt].rotated = 0;
  929.             pts[vertcnt].connected = 0;
  930.             vertcnt++;
  931.               }
  932.               break;
  933.     case 0x4120 : // Loading polygons
  934.               fread (&polys, 2, 1, in);
  935.               objectlist[totalobjects].maxframe = -1;
  936.               objectlist[totalobjects].maxchild = -1;
  937.               
  938.               objectlist[totalobjects].currentframe = 0;
  939.               objectlist[totalobjects].tstepsleft = -1;
  940.               objectlist[totalobjects].rstepsleft = -1;
  941.  
  942.               objectlist[totalobjects].scalex = 1;
  943.               objectlist[totalobjects].scaley = 1;
  944.               objectlist[totalobjects].scalez = 1;
  945.               
  946.               objectlist[totalobjects].translatex = 0;
  947.               objectlist[totalobjects].translatey = 0;
  948.               objectlist[totalobjects].translatez = 0;
  949.  
  950.               objectlist[totalobjects].start_poly = totalpoly;
  951.               for (i = 0; i < polys; i++)
  952.               {
  953.             fread (&p1, 2, 1, in);
  954.             fread (&p2, 2, 1, in);
  955.             fread (&p3, 2, 1, in);
  956.             fread (&p4, 2, 1, in);
  957.             ctr = vertcnt - vertices;
  958.             p1 += ctr;
  959.             p2 += ctr;
  960.             p3 += ctr;
  961.             
  962.             polylist[totalpoly].vertex1 = p1;
  963.             polylist[totalpoly].vertex2 = p2;
  964.             polylist[totalpoly].vertex3 = p3;
  965.             polylist[totalpoly].type = 1;
  966.             polylist[totalpoly].status = p4;
  967.             polylist[totalpoly].color = 0;
  968.             vptr = &pts[polylist[totalpoly].vertex1];
  969.             vptr2 = &pts[polylist[totalpoly].vertex2];
  970.             vptr3 = &pts[polylist[totalpoly].vertex3];
  971.             calc_normal (&pts[p3], &pts[p2], &pts[p1],
  972.                      &polylist[totalpoly].normal);
  973.             vptr->normal.x += polylist[totalpoly].normal.x;
  974.             vptr->normal.y += polylist[totalpoly].normal.y;
  975.             vptr->normal.z += polylist[totalpoly].normal.z;
  976.             vptr->connected++;
  977.             vptr2->normal.x += polylist[totalpoly].normal.x;
  978.             vptr2->normal.y += polylist[totalpoly].normal.y;
  979.             vptr2->normal.z += polylist[totalpoly].normal.z;
  980.             vptr2->connected++;
  981.             vptr3->normal.x += polylist[totalpoly].normal.x;
  982.             vptr3->normal.y += polylist[totalpoly].normal.y;
  983.             vptr3->normal.z += polylist[totalpoly].normal.z;
  984.             vptr3->connected++;
  985.     
  986.             /* Calculate center of polygon */
  987.             min_depth = vptr->local.x;
  988.             if (vptr2->local.x < min_depth)
  989.               min_depth = vptr2->local.x;
  990.             if (vptr3->local.x < min_depth)
  991.               min_depth = vptr3->local.x;
  992.             max_depth = vptr->local.x;
  993.             if (vptr2->local.x > max_depth)
  994.             max_depth = vptr2->local.x;
  995.             if (vptr3->local.x > max_depth)
  996.             max_depth = vptr3->local.x;
  997.             polylist[totalpoly].center.x = (min_depth + max_depth) / 2.0;
  998.         
  999.             min_depth = vptr->local.y;
  1000.             if (vptr2->local.y < min_depth)
  1001.             min_depth = vptr2->local.y;
  1002.             if (vptr3->local.y < min_depth)
  1003.             min_depth = vptr3->local.y;
  1004.             max_depth = vptr->local.y;
  1005.             if (vptr2->local.y > max_depth)
  1006.             max_depth = vptr2->local.y;
  1007.             if (vptr3->local.y > max_depth)
  1008.             max_depth = vptr3->local.y;
  1009.             polylist[totalpoly].center.y = (min_depth + max_depth) / 2.0;
  1010.     
  1011.             min_depth = vptr->local.z;
  1012.             if (vptr2->local.z < min_depth)
  1013.             min_depth = vptr2->local.z;
  1014.             if (vptr3->local.z < min_depth)
  1015.             min_depth = vptr3->local.z;
  1016.             max_depth = vptr->local.z;
  1017.             if (vptr2->local.z > max_depth)
  1018.             max_depth = vptr2->local.z;
  1019.             if (vptr3->local.z > max_depth)
  1020.             max_depth = vptr3->local.z;
  1021.             polylist[totalpoly].center.z = (min_depth + max_depth) / 2.0;
  1022.             totalpoly++;
  1023.               }
  1024.               objectlist[totalobjects].end_poly = totalpoly - 1;
  1025.               totalobjects++;
  1026.               fseek (in, nextobj, SEEK_SET);
  1027.               break;
  1028.     case 0x4160 : // Loading Matrix
  1029.               fread (&mat11, 4, 1, in);
  1030.               fread (&mat12, 4, 1, in);
  1031.               fread (&mat13, 4, 1, in);
  1032.               fread (&mat21, 4, 1, in);
  1033.               fread (&mat22, 4, 1, in);
  1034.               fread (&mat23, 4, 1, in);
  1035.               fread (&mat31, 4, 1, in);
  1036.               fread (&mat32, 4, 1, in);
  1037.               fread (&mat33, 4, 1, in);
  1038.               fread (&mat41, 4, 1, in);
  1039.               fread (&mat42, 4, 1, in);
  1040.               fread (&mat43, 4, 1, in);
  1041.               break;
  1042.     case 0x4600 : // Light
  1043.               fread (&lightx, 4, 1, in);
  1044.               fread (&lighty, 4, 1, in);
  1045.               fread (&lightz, 4, 1, in);
  1046.               light_x = lightx;
  1047.               light_y = lighty;
  1048.               light_z = lightz;
  1049.               break;
  1050.     case 0x4700 : // Camera
  1051.               fread (&camx, 4, 1, in);
  1052.               fread (&camy, 4, 1, in);
  1053.               fread (&camz, 4, 1, in);
  1054.               camera_x = camx;
  1055.               camera_y = camy;
  1056.               camera_z = camz;
  1057.               fread (&tarx, 4, 1, in);
  1058.               fread (&tary, 4, 1, in);
  1059.               fread (&tarz, 4, 1, in);
  1060.               focus_x = tarx;
  1061.               focus_y = tary;
  1062.               focus_z = tarz;
  1063.               fread (&bank, 4, 1, in);
  1064.               camera_angle = bank;
  1065.               fread (&lens, 4, 1, in);
  1066.               fov = cameras[0].fov;
  1067.               for (i = 1; i < 9; i++)
  1068.             if (cameras[i].lens < lens)
  1069.               fov = cameras[i].fov;
  1070.               break;
  1071.     case 0xb000 : // Keyframer data
  1072.               break;
  1073.     case 0xb002 : // Object framedata
  1074.               break;
  1075.     case 0xb010 : // Found object
  1076.               nextobj = ftell (in) + chunk.next_chunk - 6;
  1077.               
  1078.               c = 0;  /* Read the name */
  1079.               do {
  1080.             objname[c] = fgetc (in);
  1081.             c++;
  1082.               } while (objname[c-1] != 0);
  1083.  
  1084.               hiernum = find_object (objname);
  1085.               
  1086.               if (hiernum == -1)   /* Dummy object */
  1087.             hiernum = OBJBUF - 1;
  1088.  
  1089.               fread (buffer, 4, 1, in);
  1090.               fread (&level, 2, 1, in);
  1091.  
  1092.               if (level == -1)
  1093.                {
  1094.             prevobj = hiernum;
  1095.             objectlist[hiernum].parent = -1;
  1096.             objectlist[hiernum].level = -1;
  1097.                }
  1098.               else if (level > objectlist[prevobj].level)
  1099.                {
  1100.             add_child(prevobj, hiernum);
  1101.             prevobj = hiernum;
  1102.                }
  1103.               else /* Need to back up the tree */
  1104.                {
  1105.             while ((level <= objectlist[prevobj].level) && 
  1106.                (objectlist[prevobj].level > -1))
  1107.               prevobj = objectlist[prevobj].parent;
  1108.             add_child (prevobj, hiernum);
  1109.                }
  1110.  
  1111.               for (i = 0; i < MAXKEYS; i++)
  1112.                objectlist[hiernum].keylist[i].framenumber = -1;
  1113.               
  1114.               objectlist[hiernum].maxframe = -1;
  1115.               fseek (in, nextobj, SEEK_SET);
  1116.               break;
  1117.     
  1118.     case 0xb020 : // Translation key
  1119.               nextobj = ftell (in) + chunk.next_chunk - 6;
  1120.               fread (buffer, 10, 1, in);
  1121.               fread (&numkeys, 4, 1, in);
  1122.  
  1123.               for (i = 0; i < numkeys; i++)
  1124.             {
  1125.              fread (&framenumber, 2, 1, in);
  1126.              fread (&buffer, 4, 1, in);
  1127.              
  1128.              fread (&x, 4, 1, in);
  1129.              fread (&y, 4, 1, in);
  1130.              fread (&z, 4, 1, in);
  1131.              
  1132.              add_key_translate (&objectlist[hiernum],
  1133.                     framenumber, x, y, z);
  1134.                }                        
  1135.                
  1136.               fseek (in, nextobj, SEEK_SET);
  1137.               break;
  1138.     
  1139.  
  1140.     case 0xb021 : // Rotation key
  1141.               nextobj = ftell (in) + chunk.next_chunk - 6;
  1142.               fread (buffer, 10, 1, in);
  1143.               fread (&numkeys, 4, 1, in);
  1144.               
  1145.               for (i = 0; i < numkeys; i++)
  1146.             {
  1147.              fread (&framenumber, 2, 1, in);
  1148.              fread (buffer, 4, 1, in);
  1149.              
  1150.              fread (&rangle, 4, 1, in);
  1151.              fread (&rx, 4, 1, in);
  1152.              fread (&ry, 4, 1, in);
  1153.              fread (&rz, 4, 1, in);
  1154.              rangle = rangle * 180.0 / 3.1415;
  1155.              
  1156.              add_key_rotate (&objectlist[hiernum], framenumber,
  1157.               rx * rangle, ry * rangle, rz * rangle);
  1158.             }                        
  1159.               
  1160.               fseek (in, nextobj, SEEK_SET);
  1161.               break;
  1162.     case 0xb022 : // Scale key
  1163.               nextobj = ftell (in) + chunk.next_chunk - 6;
  1164.               fread (buffer, 10, 1, in);
  1165.               fread (&numkeys, 4, 1, in);
  1166.               
  1167.               for (i = 0; i < numkeys; i++)
  1168.             {
  1169.              fread (&framenumber, 2, 1, in);
  1170.              fread (buffer, 4, 1, in);
  1171.              
  1172.              fread (&rx, 4, 1, in);
  1173.              fread (&ry, 4, 1, in);
  1174.              fread (&rz, 4, 1, in);
  1175.              
  1176.              add_key_scale (&objectlist[hiernum], 
  1177.                     framenumber, rx, ry, rz);
  1178.             }                        
  1179.               
  1180.               fseek (in, nextobj, SEEK_SET);
  1181.               break;
  1182.  
  1183.     default     : fseek (in, chunk.next_chunk-6, SEEK_CUR);
  1184.       }
  1185.     if (chunk.chunk_id == 0xb001)
  1186.        break;
  1187.     
  1188.     }
  1189.   else printf ("Not a 3DS file. Invalid header.\n");
  1190.   worldpoints = vertcnt;
  1191.   for (i = 0; i < worldpoints; i++)
  1192.   {
  1193.     pts[i].normal.x /= (float)pts[i].connected;
  1194.     pts[i].normal.y /= (float)pts[i].connected;
  1195.     pts[i].normal.z /= (float)pts[i].connected;
  1196.   }
  1197.   fclose (in);
  1198.   if ((camera_x == focus_x) && (camera_y == focus_y) && (camera_z == focus_z))
  1199.   {
  1200.     printf ("No camera loaded. Default view position set.\n");
  1201.     camera_x = -400;
  1202.     camera_y = -400;
  1203.     camera_z = -400;
  1204.   }
  1205.  
  1206.  build_hierarchy ();   /* Not complete yet */
  1207.  
  1208.  l3dsstop:;
  1209.  if (libf != NULL)
  1210.    fclose (libf);
  1211. }
  1212.  
  1213.  
  1214. int compare (sort *a, sort *b)
  1215. /* Used for sorting */
  1216. {
  1217. float comp;  
  1218.   
  1219.   comp = a->depth - b->depth;
  1220.  
  1221.   //if (abs(comp) < 0.0005)
  1222.     //return 0;
  1223.   if (comp < 0)
  1224.     return 1;
  1225.   else return -1;
  1226. }
  1227.  
  1228.  
  1229. void draw_polys (vertex *pts, int drawtotal)
  1230. /* Draw all of the polygons in order, using our rendering method */
  1231. {
  1232. char shade;
  1233. int d, e;
  1234. int first;
  1235. float dotprod;
  1236. triangle_3d *ptr;
  1237. vertex *vptr;
  1238. vertex *vptr2;
  1239. vertex *vptr3;
  1240. sort tempsort;
  1241. point3d *lightnorm;
  1242. float lnormx, lnormy, lnormz;  
  1243. int polynum;
  1244.  
  1245.   lightnorm = &light.normal;
  1246.   
  1247.   for (d = 0; d < worldpoints; d++)
  1248.     pts[d].rotated = 0;
  1249.   
  1250.   qsort (sorted_polys, drawtotal, sizeof (sort), compare);        
  1251.  
  1252.   lnormx = lightnorm->x;
  1253.   lnormy = lightnorm->y;
  1254.   lnormz = lightnorm->z;
  1255.   
  1256.   first = drawtotal - 1;
  1257.   for (d = 0; d <= first; d++)
  1258.   {
  1259.     polynum = sorted_polys[d].number;
  1260.     
  1261.     ptr = &polylist[polynum];
  1262.     vptr = &pts[ptr->vertex1];
  1263.     vptr2 = &pts[ptr->vertex2];
  1264.     vptr3 = &pts[ptr->vertex3];
  1265.     
  1266.     renderpoly[0].x = vptr->screenx;
  1267.     renderpoly[0].y = vptr->screeny;
  1268.     renderpoly[1].x = vptr2->screenx;
  1269.     renderpoly[1].y = vptr2->screeny;
  1270.     renderpoly[2].x = vptr3->screenx;
  1271.     renderpoly[2].y = vptr3->screeny;
  1272.  
  1273.     vptr->rotated = 0;
  1274.     vptr2->rotated = 0;
  1275.     vptr3->rotated = 0;
  1276.     
  1277.     if (ptr->type == WIREFRAME)
  1278.       {
  1279.     wsetcolor (ptr->color);
  1280.     if (ptr->status & 4)
  1281.       wline (renderpoly[0].x, renderpoly[0].y, renderpoly[1].x, renderpoly[1].y);
  1282.     if (ptr->status & 2)
  1283.       wline (renderpoly[1].x, renderpoly[1].y, renderpoly[2].x, renderpoly[2].y);
  1284.     if (ptr->status & 1)
  1285.       wline (renderpoly[2].x, renderpoly[2].y, renderpoly[0].x, renderpoly[0].y);
  1286.       }
  1287.     else if (ptr->type == SOLID)
  1288.       {
  1289.     dotprod = (ptr->normal.x * lnormx) + (ptr->normal.y * lnormy) +
  1290.           (ptr->normal.z * lnormz);
  1291.     
  1292.     if (dotprod < 0)
  1293.       renderpoly[0].col = dotprod * render_shades;
  1294.     else renderpoly[0].col = 0;
  1295.     
  1296.     wsetcolor (ptr->color - renderpoly[0].col);
  1297.     wtriangle_solid (renderpoly);
  1298.       }
  1299.     else if (ptr->type == GOURAUD)
  1300.       {
  1301.     dotprod = (vptr->normal.x * lnormx) + (vptr->normal.y * lnormy) +
  1302.           (vptr->normal.z * lnormz);
  1303.     if (dotprod > 0)
  1304.       dotprod = 0;
  1305.     renderpoly[0].col = ptr->color - dotprod * render_shades;
  1306.  
  1307.     dotprod = (vptr2->normal.x * lnormx) + (vptr2->normal.y * lnormy) +
  1308.           (vptr2->normal.z * lnormz);
  1309.     if (dotprod > 0)
  1310.       dotprod = 0;
  1311.     renderpoly[1].col = ptr->color - dotprod * render_shades;
  1312.       
  1313.     dotprod = (vptr3->normal.x * lnormx) + (vptr3->normal.y * lnormy) +
  1314.           (vptr3->normal.z * lnormz);
  1315.     if (dotprod > 0)
  1316.       dotprod = 0;
  1317.     renderpoly[2].col = ptr->color - dotprod * render_shades;
  1318.  
  1319.     wtriangle_gouraud (renderpoly);
  1320.       }
  1321.     else if (ptr->type == TEXTURE)
  1322.       { 
  1323.        renderpoly[0].sx = ptext[polynum].sx[0];
  1324.        renderpoly[0].sy = ptext[polynum].sy[0];
  1325.        renderpoly[1].sx = ptext[polynum].sx[1];
  1326.        renderpoly[1].sy = ptext[polynum].sy[1];
  1327.        renderpoly[2].sx = ptext[polynum].sx[2];
  1328.        renderpoly[2].sy = ptext[polynum].sy[2];
  1329.      
  1330.        wtriangle_texture (renderpoly, textures[ptr->color]);
  1331.       }
  1332.     else if (ptr->type == FLAT_SHADED_TEXTURE)
  1333.       {
  1334.     dotprod = (ptr->normal.x * lnormx) + (ptr->normal.y * lnormy) +
  1335.           (ptr->normal.z * lnormz);
  1336.     if (dotprod < 0)
  1337.       shade = -dotprod * render_shades;
  1338.     else shade = 0;
  1339.  
  1340.     renderpoly[0].sx = ptext[polynum].sx[0];
  1341.     renderpoly[0].sy = ptext[polynum].sy[0];
  1342.     renderpoly[1].sx = ptext[polynum].sx[1];
  1343.     renderpoly[1].sy = ptext[polynum].sy[1];
  1344.     renderpoly[2].sx = ptext[polynum].sx[2];
  1345.     renderpoly[2].sy = ptext[polynum].sy[2];
  1346.        
  1347.     wtriangle_flat_shaded_texture (renderpoly, textures[ptr->color], 
  1348.         shade, render_shadetable);
  1349.       }
  1350.     else if (ptr->type == GOURAUD_SHADED_TEXTURE)
  1351.       {
  1352.     dotprod = (vptr->normal.x * lnormx) + (vptr->normal.y * lnormy) +
  1353.           (vptr->normal.z * lnormz);
  1354.     if (dotprod > 0)
  1355.       dotprod = 0;
  1356.     renderpoly[0].col = -dotprod * render_shades;
  1357.      
  1358.     dotprod = (vptr2->normal.x * lnormx) + (vptr2->normal.y * lnormy) +
  1359.           (vptr2->normal.z * lnormz);
  1360.     if (dotprod > 0)
  1361.       dotprod = 0;
  1362.     renderpoly[1].col = -dotprod * render_shades;
  1363.       
  1364.     dotprod = (vptr3->normal.x * lnormx) + (vptr3->normal.y * lnormy) +
  1365.           (vptr3->normal.z * lnormz);
  1366.     if (dotprod > 0)
  1367.       dotprod = 0;
  1368.     renderpoly[2].col = -dotprod * render_shades;
  1369.      
  1370.     renderpoly[0].sx = ptext[polynum].sx[0];
  1371.     renderpoly[0].sy = ptext[polynum].sy[0];
  1372.     renderpoly[1].sx = ptext[polynum].sx[1];
  1373.     renderpoly[1].sy = ptext[polynum].sy[1];
  1374.     renderpoly[2].sx = ptext[polynum].sx[2];
  1375.     renderpoly[2].sy = ptext[polynum].sy[2];
  1376.  
  1377.     wtriangle_gouraud_shaded_texture (renderpoly, textures[ptr->color],
  1378.             render_shadetable);
  1379.       }
  1380.     else if (ptr->type == TRANSLUCENT_TEXTURE)
  1381.       { 
  1382.        renderpoly[0].sx = ptext[polynum].sx[0];
  1383.        renderpoly[0].sy = ptext[polynum].sy[0];
  1384.        renderpoly[1].sx = ptext[polynum].sx[1];
  1385.        renderpoly[1].sy = ptext[polynum].sy[1];
  1386.        renderpoly[2].sx = ptext[polynum].sx[2];
  1387.        renderpoly[2].sy = ptext[polynum].sy[2];
  1388.      
  1389.        wtriangle_translucent_texture (renderpoly, textures[ptr->color], 
  1390.             render_shadetable);
  1391.       }
  1392.     else if (ptr->type == TRANSLUCENT_GOURAUD)
  1393.       { 
  1394.     dotprod = (vptr->normal.x * lnormx) + (vptr->normal.y * lnormy) +
  1395.           (vptr->normal.z * lnormz);
  1396.     if (dotprod > 0)
  1397.       dotprod = 0;
  1398.     renderpoly[0].col = ptr->color - dotprod * render_shades;
  1399.  
  1400.     dotprod = (vptr2->normal.x * lnormx) + (vptr2->normal.y * lnormy) +
  1401.           (vptr2->normal.z * lnormz);
  1402.     if (dotprod > 0)
  1403.       dotprod = 0;
  1404.     renderpoly[1].col = ptr->color - dotprod * render_shades;
  1405.       
  1406.     dotprod = (vptr3->normal.x * lnormx) + (vptr3->normal.y * lnormy) +
  1407.           (vptr3->normal.z * lnormz);
  1408.     if (dotprod > 0)
  1409.       dotprod = 0;
  1410.     renderpoly[2].col = ptr->color - dotprod * render_shades;
  1411.  
  1412.     wtriangle_translucent_gouraud (renderpoly, render_shadetable);
  1413.       }
  1414.  
  1415.   }
  1416. }
  1417.  
  1418.  
  1419.  
  1420.  
  1421. void map_plane (float x, float y, float z, long *u, long *v, float scale)
  1422. /* Given a 3D point, maps the point onto the x/y plane */
  1423. {
  1424.  *u = x * scale;
  1425.  *v = y * scale;
  1426. }
  1427.  
  1428.  
  1429.  
  1430. void wset_object_color (int obj, unsigned char col)
  1431. /* Sets the color of each triangle in an object, used for solid, gouraud, and
  1432.    texture.  For textured objects, the color represents the texture number
  1433.    from the textures array. */
  1434. {
  1435. int poly;
  1436. object_3d *objp;
  1437.  
  1438.  objp = &objectlist[obj];
  1439.  
  1440.  for (poly = objp->start_poly; poly <= objp->end_poly; poly++)
  1441.    polylist[poly].color = col;
  1442.  
  1443. }
  1444.  
  1445.  
  1446. void wset_object_type (int obj, int type)
  1447. /* Sets the rendering method for an object */
  1448. {
  1449. int poly;
  1450. object_3d *objp;
  1451.  
  1452.  objp = &objectlist[obj];
  1453.  
  1454.  for (poly = objp->start_poly; poly <= objp->end_poly; poly++)
  1455.    polylist[poly].type = type;
  1456.  
  1457. }
  1458.  
  1459.  
  1460. void wreset_3d_system (void)
  1461. /* Resets the engine so you can load in a new object */
  1462. {
  1463.  totalpoly = 0;
  1464.  totalobjects = 0;
  1465. }
  1466.  
  1467.  
  1468.